package com.hdd.biz.app.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.hdd.biz.app.dto.AppResponse;
import com.hdd.biz.app.dto.PayRequest;
import com.hdd.biz.app.entity.PaymentResult;
import com.hdd.biz.app.mapper.APPPaintingWorksMapper;
import com.hdd.biz.app.service.PayService;
import com.hdd.biz.app.service.UserAccountService;
import com.hdd.biz.app.service.UserCenterService;
import com.hdd.biz.finance.entity.Paymet;
import com.hdd.biz.finance.service.PaymetService;
import com.hdd.biz.member.entity.Member;
import com.hdd.biz.member.service.MemberService;
import com.hdd.biz.painting.entity.PaintingWorks;
import com.hdd.biz.painting.service.PaintingWorksService;
import com.hdd.config.Constant;
import com.hdd.utils.NumberUtils;
import com.hdd.utils.TimeUtils;
import com.hdd.utils.UUIDGenerator;
import com.hdd.utils.wx.AliyunDysmsUtils;
import com.hdd.utils.wx.RedisUtil;
import com.hdd.utils.wx.WxMiniProgramUtil;
import com.hdd.utils.wxUtils.Arith;
import com.hdd.utils.wxUtils.Result;
import com.hdd.utils.wxUtils.WeiXinPayService;
import com.hdd.utils.wxUtils.WeiXinPayXmlParser;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@Service
@Slf4j
public class PayServiceImpl implements PayService {


    @Autowired
    private WeiXinPayService weiXinPayService;
    @Autowired
    private UserCenterService userCenterService;
    @Autowired
    private APPPaintingWorksMapper appPaintingWorksMapper;
    @Autowired
    private PaymetService paymetService;
    @Autowired
    private UserAccountService accountService;
    @Autowired
    private WxMiniProgramUtil wxMiniProgramUtil;
    @Autowired
    private MemberService memberService;
    @Autowired
    private PaintingWorksService paintingWorksService;
    @Autowired
    private RedisUtil redisUtil;

    @Override
    @Transactional
    public AppResponse rewardAuthorByWX(PayRequest request) {
        AppResponse response = new AppResponse();
        //获取充值用户信息
        Member user = userCenterService.getUser(request.getUserId());
        if (null == user) {
            response.setCode(-1000);
            response.setMessage("用户不存在");
            return response;
        }

        if(user.getDelFlag()==1){
            response.setCode(-1000);
            response.setMessage("禁止打赏");
            return response;
        }

        //根据作品获取作者用户id
        QueryWrapper queryWrapper = new QueryWrapper();
        queryWrapper.eq("id",request.getWorksId());
        PaintingWorks paintingWorks = appPaintingWorksMapper.selectOne(queryWrapper);
        Result<?> result = rewardCondition(user, paintingWorks, request.getAmount());
        if (!result.getSuccess()) {
            response.setCode(-1000);
            response.setMessage(result.getMsg());
            return response;
        }

        String orderNum = UUIDGenerator.generate();
        //生成待付款成功订单
        Paymet payment = new Paymet();
        payment.setPaymentNo(orderNum);
        payment.setAmount(new BigDecimal(request.getAmount()));
        payment.setUserId(request.getUserId());
        payment.setWorksUserId(paintingWorks.getUserId());
        payment.setWorksNo(request.getWorksId());
        payment.setRate(Constant.WEIXIN_RATE+"");
        payment.setRealityAmount(NumberUtils.m1(Double.parseDouble(request.getAmount()),Constant.WEIXIN_RATE));
        payment.setChargeAmount(NumberUtils.m3(request.getAmount(),payment.getRealityAmount()));
        payment.setStatus("D");
        payment.setRemark(request.getRemark());
        payment.setPayMode("1");
        payment.setAnonymity(request.getAnonymity());
        payment.setIfOpen("F");
        paymetService.insertPaymeny(payment);

        //统一下单，组装数据返回前端，调用支付
        int money = new Double(Arith.mul(Double.parseDouble(payment.getAmount().toString()), 100)).intValue();
        Result<Map<String, Object>> mapResult =   weiXinPayService.unifiedorder(orderNum, money, user.getXcxOpenid(), "", "/app/pay/unifiedorderNotify");
        log.info(mapResult.toString());
        if(!mapResult.getSuccess()){
            response.setCode(-1000);
            response.setMessage(mapResult.getMsg());
            return response;
        }
        PaymentResult paymentResult = new PaymentResult();
        paymentResult.setNonceStr(mapResult.getData().get("nonceStr").toString());
        paymentResult.setPaySign(mapResult.getData().get("paySign").toString());
        paymentResult.setPackageStr(mapResult.getData().get("package").toString());
        paymentResult.setTimeStamp(mapResult.getData().get("timeStamp").toString());
        paymentResult.setSignType("MD5");
        response.setItem(paymentResult);
        return response;
    }


    @Override
    public String  unifiedorderNotify(HttpServletRequest request) {
        log.info("进入回调函数");
        String resultXml = WeiXinPayXmlParser.requestToString(request);
        log.info("微信回调响应参数：{}", resultXml);
        Map<String, Object> xmlMap = WeiXinPayXmlParser.xmlFormatStringToMap(resultXml);
        //验证是否成功，如果成功则正常返回，如果不成功则返回null
        if (null == xmlMap || null == xmlMap.get("result_code") || !"SUCCESS".equals(xmlMap.get("result_code").toString().toUpperCase())) {
            return null;
        }
        //验证订单真实性
        if (!weiXinPayService.verifyOrder(xmlMap)) {
            return null;
        }
        String transactionId = (String) xmlMap.get("transaction_id");

        //支付成功后调用查询接口，验证订单是否完成，如果完成则修改支付订单状态
        Map<String, Object> queryResultMap = weiXinPayService.queryUnifiedorder(xmlMap.get("out_trade_no").toString());
        if (null == queryResultMap.get("return_code") || !"SUCCESS".equals(queryResultMap.get("return_code").toString().toUpperCase())) {
            return null;
        }
        if (null == queryResultMap.get("result_code") || !"SUCCESS".equals(queryResultMap.get("result_code").toString().toUpperCase())) {
            return null;
        }

        /*SUCCESS—支付成功
        REFUND—转入退款
        NOTPAY—未支付
        CLOSED—已关闭
        REVOKED—已撤销（刷卡支付）
        USERPAYING--用户支付中
        PAYERROR--支付失败(其他原因，如银行返回失败)*/
        if (null == queryResultMap.get("trade_state") || !"SUCCESS".equals(queryResultMap.get("trade_state").toString().toUpperCase())) {
            //支付失败，修改支付记录状态
            Paymet payment = paymetService.findPayMent(queryResultMap.get("out_trade_no").toString());
            if (null != payment && payment.getStatus().equals("D")) {
                log.info("支付失败");
                //修改状态
                payment.setStatus("F");
                paymetService.updateById(payment);
            }
            return null;
        }
        //支付成功，修改支付记录状态

        Paymet payment = paymetService.findPayMent(queryResultMap.get("out_trade_no").toString());
        if (null != payment && payment.getStatus().equals("D")) {
            log.info("支付成功");
            redisUtil.set("paymentTips:"+payment.getWorksUserId(),payment.getWorksUserId());
            redisUtil.incr("paymentAmount:"+payment.getWorksNo(),1);

            if(redisUtil.hasKey("paymentAmountSum:"+payment.getWorksUserId())){
                BigDecimal bigDecimal = new BigDecimal(redisUtil.get("paymentAmountSum:"+payment.getWorksUserId()).toString());
                if(bigDecimal!=null){
                    redisUtil.set("paymentAmountSum:"+payment.getWorksUserId(),new BigDecimal(payment.getRealityAmount()).add(bigDecimal));
                }
            }else{
                redisUtil.set("paymentAmountSum:"+payment.getWorksUserId(),payment.getRealityAmount());
            }

            Member member = memberService.findMemberByUid(payment.getUserId());
            PaintingWorks works = paintingWorksService.findWorksById(payment.getWorksNo());
            //修改状态
            payment.setStatus("T");
            paymetService.updateById(payment);
            //增加钱
            accountService.rewardByWX(payment.getUserId(),works.getUserId(),payment.getRealityAmount().toString(),payment.getChargeAmount(),payment.getRealityAmount(),payment.getRate(),1);

            String name = "神秘人物";
            //小程序推送
            if("T".equals(payment.getAnonymity())){
                wxMiniProgramUtil.sendRewardMessage(works.getUserId(), works.getPaintingName(), "神秘人物", Double.parseDouble(payment.getRealityAmount()),payment.getWorksNo());
            }else{
                wxMiniProgramUtil.sendRewardMessage(works.getUserId(), works.getPaintingName(), member.getNickname(), Double.parseDouble(payment.getRealityAmount()),payment.getWorksNo());
                name  = member.getNickname();
            }

            Member worksMember = memberService.findMemberByUid(works.getUserId());
            if(StringUtils.isNotEmpty(worksMember.getPhone())){ //给用户发送短信
                sendMessageByReward(worksMember.getId(),worksMember.getPhone(),works.getPaintingName(),name,3);
            }
        }

        Map<String, Object> map = new HashMap<>();
        map.put("return_code", "<![CDATA[SUCCESS]]>");
        map.put("return_msg", "<![CDATA[OK]]>");
        return WeiXinPayXmlParser.mapToXmlFormatString(map);
    }


    @Override
    @Transactional
    public AppResponse rewardAuthorByBalance(PayRequest request) {
        AppResponse response = new AppResponse();
        //获取充值用户信息
        Member user = userCenterService.getUser(request.getUserId());
        if (null == user) {
            response.setCode(-1000);
            response.setMessage("用户不存在");
            return response;
        }

        //根据作品获取作者用户id
        QueryWrapper queryWrapper = new QueryWrapper();
        queryWrapper.eq("id",request.getWorksId());
        PaintingWorks paintingWorks = appPaintingWorksMapper.selectOne(queryWrapper);


        if(request.getUserId().equals(paintingWorks.getUserId())){
            response.setCode(-1000);
            response.setMessage("赞赏自己仅支持微信支付");
            return response;
        }


        Result<?> result = rewardCondition(user, paintingWorks, request.getAmount());
        if (!result.getSuccess()) {
            response.setCode(-1000);
            response.setMessage(result.getMsg());
            return response;
        }

        String orderNum = UUIDGenerator.generate();
        //生成待付款成功订单
        Paymet payment = new Paymet();
        payment.setPaymentNo(orderNum);
        payment.setAmount(new BigDecimal(request.getAmount()));
        payment.setUserId(request.getUserId());
        payment.setWorksUserId(paintingWorks.getUserId());
        payment.setWorksNo(request.getWorksId());
        payment.setRate("0");
        payment.setChargeAmount("0.00");
        payment.setRealityAmount(request.getAmount());
        payment.setStatus("F");
        payment.setRemark(request.getRemark());
        payment.setPayMode("1");
        payment.setAnonymity(request.getAnonymity());
        payment.setIfOpen("F");

        //判断余额
        response =  accountService.reward(request.getUserId(),paintingWorks.getUserId(),request.getAmount());
        if(response.getCode()>0){
            payment.setStatus("T");
            paymetService.insertPaymeny(payment);
            redisUtil.set("paymentTips:"+payment.getWorksUserId(),payment.getWorksUserId());
            redisUtil.incr("paymentAmount:"+payment.getWorksNo(),1);

            if(redisUtil.hasKey("paymentAmountSum:"+payment.getWorksUserId())){
             BigDecimal bigDecimal = new BigDecimal(redisUtil.get("paymentAmountSum:"+payment.getWorksUserId()).toString());
             if(bigDecimal!=null){

                 redisUtil.set("paymentAmountSum:"+payment.getWorksUserId(),payment.getAmount().add(bigDecimal));
             }
            }else{
                redisUtil.set("paymentAmountSum:"+payment.getWorksUserId(),payment.getAmount());
            }
            return response;
        }
        return response;
    }



    private Result<?> rewardCondition(Member user, PaintingWorks paintingWorks, String amount) {
        if (null == paintingWorks) {
            return new Result<>(false, "作品不存在");
        } else if (null == paintingWorks.getUserId() || "".equals(paintingWorks.getUserId())) {
            return new Result<>(false, "作者不存在");
        } else if (user.getId().equals(paintingWorks.getUserId())) {
            return new Result<>(false, "不能赞赏自己");
        }  else if (Double.parseDouble(amount) <= 0) {
            return new Result<>(false, "赞赏金额不能为负数");
        } else if (paintingWorks.getAllowReward() == 1) {
            return new Result<>(false, "作品不允许被赞赏");
        }
        return new Result<>(true);
    }


    /**
     * 给用户发送打赏短信 一天最多3次
     * @param id
     * @param phone
     * @param title
     * @param name
     * @param maxNums
     */
    public void sendMessageByReward(Integer id,String phone,String title,String name,Integer maxNums){
        if(redisUtil.hasKey("messageByReward:"+ TimeUtils.getTime2()+":"+id)){
            Integer nums =  Integer.parseInt(redisUtil.get("messageByReward:"+ TimeUtils.getTime2()+":"+id).toString());
            if(nums<maxNums){ //一天最多三次
                System.out.println("发送短信");
                AliyunDysmsUtils.sendMessageByReward(phone,title,name);
                redisUtil.set("messageByReward:"+ TimeUtils.getTime2()+":"+id,nums+1, TimeUnit.DAYS.toDays(60*60*24));
            }
        }else{
            AliyunDysmsUtils.sendMessageByReward(phone,title,name);
            redisUtil.set("messageByReward:"+ TimeUtils.getTime2()+":"+id,1, TimeUnit.DAYS.toDays(60*60*24));
        }
    }
}
